package main

import "fmt"

/**
特别注意:
当我们初始化一个结构体直接去调用他绑定的函数时，这里不需要在意接收者的数据类型，因为go内部可以进行转换
但是我们通过一个普通方法去统一调用绑定的函数是，要和接收者数据类型一致，否则会编译不过
 */

type face interface {
	sayhi()
}

type Xue struct {
	name string
	id int
}

func (tmp *Xue) sayhi()  {
	fmt.Printf("a[%s, %d]\n", tmp.name, tmp.id)
}

type Lao struct {
	name string
	number int
}

func (tmp *Lao) sayhi()  {
	fmt.Printf("b[%s, %d]\n", tmp.name, tmp.number)
}

type Mys string

func (tmp *Mys) sayhi()  {
	fmt.Printf("c = %s\n", *tmp)
}

//统一的一个接口，参数是上边定义的接口的名字face
func whosayhi(i face)  {
	i.sayhi()
}

func main()  {
	a := &Xue{"make", 21}
	l := a
	l.sayhi()

	b := &Lao{"tea", 23456}
	s := b
	s.sayhi()

	var sss Mys = "trt"
	ss := sss
	ss.sayhi()

	//使用一个统一的函数实现接口的方法
	fmt.Println("---------------------------")
	//a是取得变量地址，所以不用再加地址符
	whosayhi(a)
	//b是取得变量地址，所以不用再加地址符
	whosayhi(b)
	//c是一个普通的变量，要加地址符
	whosayhi(&sss)

	//使用切片，循环调用
	fmt.Println("---------------------------")
	//这里切片的数据类型也是要用我们定义的接口的名字 face
	jihe := make([]face, 3)
	jihe[0] = a
	jihe[1] = b
	jihe[2] = &sss
	for _, i := range jihe {
		whosayhi(i)
	}

}